﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace OnlineScheduling.DomainModel
{
    public class Task : IComparable, ICloneable
    {

        public int Id { get; private set; }
        public int Duration { get; private set; }
        public int Weight { get; private set; }
        public int ProceededTime { get; private set; }
        public int TimeIn { get; private set; }
        public int TimeFinished { get; private set; }
        public TasksPriorityType PriorityType { get; set; }
        public int TimePutOnProcessor { get; private set; }
        public int ProcessorId { get; private set; }
        public bool WasDelayed { get; set; }

        public bool IsBeingProceeded
        {
            get
            {
                return ProcessorId != -1;
            }
        }

        public int ExpectedTimeToBeDone
        {
            get
            {
                if (IsBeingProceeded) return TimePutOnProcessor + TimeNeeded;
                return -1;
            }
        }

        public bool IsDone 
        { 
            get
            {
                return ProceededTime == Duration;
            } 
        }

        public double PriorityValue
        {
            get
            {
                double result = 0;
                switch (PriorityType)
                {
                    case TasksPriorityType.NoPriority: result = 0; break;
                    case TasksPriorityType.ByWeightDurationDivision: result = (double)Weight / (double)Duration; break;
                    case TasksPriorityType.ByWeightSRTDivision: result = (double)Weight / (double)TimeNeeded; break;
                    case TasksPriorityType.ByArrivalTime: result = TimeIn; break;
                }

                return result;
            }
        }

        public int TimeNeeded
        {
            get
            {
                return Duration - ProceededTime;
            }
        }

        public void ResumeOrStart(int time, int idProcessor)
        {
            TimePutOnProcessor = time;
            ProcessorId = idProcessor;
        }

        public void StopProceeding(int time)
        {
            ProceededTime += time - TimePutOnProcessor;
            if (IsDone) TimeFinished = time;
            TimePutOnProcessor = -1;
            ProcessorId = -1;
        }



        public Task(int id, int duration, int weight, TasksPriorityType priorityType, int timeIn)
        {
            Id = id;
            Duration = duration;
            PriorityType = priorityType;
            Weight = weight;
            ProceededTime = 0;
            TimeIn = timeIn;
            TimeFinished = -1;
            TimePutOnProcessor = -1;
            ProcessorId = -1;
            WasDelayed = false;
          
        }

        #region IComparable Members

        public int CompareTo(object obj)
        {
            int result = 0;
            Task compared = obj as Task;
            switch (PriorityType)
            {
                case TasksPriorityType.NoPriority: 
                    result = 0; 
                    break;
                case TasksPriorityType.ByWeightDurationDivision:
                    if (PriorityValue > compared.PriorityValue) result = 1;
                    else if (PriorityValue == compared.PriorityValue) result = 0;
                    else result = -1;
                    break;
                case TasksPriorityType.ByWeightSRTDivision:
                    if (PriorityValue > compared.PriorityValue) result = 1;
                    else if (PriorityValue == compared.PriorityValue) result = 0;
                    else result = -1;
                    break;
                case TasksPriorityType.ByArrivalTime:
                    if (TimeIn < compared.TimeIn) result = 1;
                    else if (TimeIn == compared.TimeIn) result = 0;
                    else result = -1;
                    break;
            }

            return result;
        }

        #endregion

        #region ICloneable Members

        public object Clone()
        {
           return new Task(Id,Duration,Weight,PriorityType,TimeIn);
        }

        #endregion
    }
}
